/*
 * @(#)Cache.java    0.5 29/08/2009
 */
package com.ly.mpayment.persist.catstorage;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 缓存
 * <p>缺省容量为100，可以通过在初始化时使用capacity参数调整缓存容量的大小。
 * 当缓存空余容量为0时，采用LRU策略清理过期缓存。本缓存是线程安全的。</p>
 * 
 * @version 0.5
 * @since 0.5
 */
@SuppressWarnings("serial")
public class Cache<K, V> extends LinkedHashMap<K, V> {

    /**
     * 缓存容量
     */
    private int capacity;
    /**
     * 线程互斥锁
     */
    private final Lock lock = new ReentrantLock();
    /**
     * 缺省缓存容量
     */
    private final static int DEFAULT_CAPACITY = 100;
    /**
     * 缺省加载因子
     */
    private final static float DEFAULT_LOADFACTOR = 0.75f;

    /**
     * 缺省构造方法，创建一个容量为100的缓存对象
     * @since 0.5
     */
    public Cache() {
        super(DEFAULT_CAPACITY, DEFAULT_LOADFACTOR, true);
        this.capacity = DEFAULT_CAPACITY;
    }

    /**
     * 构造方法，创建制定容量的缓存对象
     * @param capacity 缓存容量
     * @since 0.5
     */
    public Cache(int capacity) {
        super(capacity, DEFAULT_LOADFACTOR, true);
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return this.size() > capacity;
    }

    @Override
    public boolean containsKey(Object key) {
        try {
            lock.lock();
            return super.containsKey(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V get(Object key) {
        try {
            lock.lock();
            return super.get(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V put(K key, V value) {
        try {
            lock.lock();
            return super.put(key, value);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public int size() {
        try {
            lock.lock();
            return super.size();
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void clear() {
        try {
            lock.lock();
            super.clear();
        } finally {
            lock.unlock();
        }
    }
}
